package ro.msg.quiz.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.swing.JOptionPane;

import ro.msg.quiz.dao.AnswersDB;
import ro.msg.quiz.dao.DatabaseCon;
import ro.msg.quiz.dao.QuestionDB;
import ro.msg.quiz.dao.QuizDB;
import ro.msg.quiz.dao.RelationQuizzAndQuestionsDB;
import ro.msg.quiz.domain.MultipleChoiceQuestion;
import ro.msg.quiz.domain.Question;
import ro.msg.quiz.domain.QuestionType;
import ro.msg.quiz.domain.Quiz;
import ro.msg.quiz.domain.SingleChoiceQuestion;
import ro.msg.quiz.domain.TextQuestion;
import ro.msg.quiz.exception.MyException;
import ro.msg.quiz.service.IService;
import ro.msg.quiz.service.QuestionService;
import ro.msg.quiz.service.QuizService;
import ro.msg.quiz.view.AddNewQuestion;
import ro.msg.quiz.view.AddNewQuiz1;
import ro.msg.quiz.view.AddNewQuiz2;
import ro.msg.quiz.view.EditQuiz;
import ro.msg.quiz.view.MultipleChoiceWindow;
import ro.msg.quiz.view.SmartQuest;

//AUTHORS: Ervin, Marco, Roxana

//Class responsible for communicating between persistence data and different views
public class Controller implements ActionListener, KeyListener {
    private SmartQuest smartQ;
    private AddNewQuestion addQuestion;
    private AddNewQuiz1 addQuestionnaire;
    private AddNewQuiz2 addQuestionnaire2;
    private MultipleChoiceWindow multipleView;
    private EditQuiz editQuiz;
    private AddNewQuestion editQuestion;
    private GuiService guiService;
    private IService<Quiz> quizzesService;
    private IService<Question> questionsService;

    private boolean createQuiz = false, createQuestion = false;

    public Controller() throws ClassNotFoundException, SQLException {
	guiService = new GuiService();
	quizzesService = new QuizService();
	questionsService = new QuestionService();
	smartQ = new SmartQuest(guiService.getQuizzesAndNrOfQuestions(), guiService.getQuestionsAndType());
	this.addActionListenersSmartQ();
	new DatabaseCon();
    }

    private void addActionListenersSmartQ() {
	smartQ.getAdd().addActionListener(this);
	smartQ.getDelete().addActionListener(this);
	smartQ.getExport().addActionListener(this);
	smartQ.getEdit().addActionListener(this);
	smartQ.getImportt().addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
	Object obj = arg0.getSource();

	// /////////////////////SmartQuest////////////////////////////
	if (obj.equals(smartQ.getAdd())) {

	    if (smartQ.getTabs().getSelectedIndex() == 1) {
		addQuestion = new AddNewQuestion("", QuestionType.MULTIPLE_CHOICE_Q, 2);
		this.addQuestionAddListeners();
		createQuestion = true;
	    }

	    else {
		addQuestionnaire = new AddNewQuiz1();
		this.addQuestionnaireAddListeners();
		createQuiz = true;
	    }

	}

	if (obj.equals(smartQ.getEdit())) {
	    try {
		String editQInfo[] = new String[5];
		editQInfo = smartQ.getEditInfo();
		int selectedRow = Integer.parseInt(editQInfo[4]);
		if (smartQ.getTabs().getSelectedIndex() == 1) {

		    Question q = ((ArrayList<Question>) guiService.getQuestionsList()).get(selectedRow);
		    int posAnsw = 0;
		    if (q.getType().equals(QuestionType.TEXT_Q))
			q = (TextQuestion) q;
		    else {

			List<String> options = new ArrayList<String>();
			if (q.getType().equals(QuestionType.MULTIPLE_CHOICE_Q)) {
			    options = ((MultipleChoiceQuestion) q).getOptions();

			} else if (q.getType().equals(QuestionType.SINGLE_CHOICE_Q))
			    options = ((SingleChoiceQuestion) q).getOptions();

			posAnsw = options.size();
		    }

		    editQuestion = new AddNewQuestion(editQInfo[0], q.getType(), posAnsw);
		    this.editQuestionAddListeners();

		} else {
		    editQuiz = new EditQuiz(editQInfo[0], guiService.getQuestions());
		    this.editQuizAddListeners();
		    // String data[]=new String[4];
		    // data[0] =
		    // guiService.getQuizzesList().get(selectedRow).getName();
		    // data[1] =
		    // Integer.toString(guiService.getQuizzesList().get(selectedRow).getQuestionList().size());
		    // data[2] = "Last modified unknown";
		    // data[3] = "Quiz";
		    // smartQ.updateTable(selectedRow, data, editQInfo[3]);
		}

		// smartQ.updateTable(selectedRow, data, editQInfo[3]);

	    } catch (ArrayIndexOutOfBoundsException e) {
		JOptionPane.showMessageDialog(null, "Please select an item from table to edit!");
	    }
	}

	if (obj.equals(smartQ.getDelete())) {
	    if (smartQ.getTabs().getSelectedIndex() == 0) {
		try {
		    String quizzes[] = new String[smartQ.getSelectedRows().length];
		    quizzes = smartQ.getSelectedRows();
		    for (int i = 0; i < quizzes.length; i++) {
			quizzesService.delete(quizzes[i]);
			QuizDB.deleteQuiz(quizzes[i]);
		    }
		} catch (Exception e) {
		    JOptionPane.showMessageDialog(null, e.toString());
		}
	    } else {
		try {
		    questionsService.delete(smartQ.getSelectedItem());
		    String questions[] = smartQ.getSelectedRows();
		    for (int i = 0; i < questions.length; i++)
			QuestionDB.deleteQuestion(questions[i]);
		} catch (Exception e) {
		    JOptionPane.showMessageDialog(null, e.toString());
		}
	    }

	    smartQ.deleteRow();
	}
	if (obj.equals(smartQ.getExport())) {
	    new ExportXML();
	    JOptionPane.showMessageDialog(null, "The data has been exported to a xml file!");
	}
	if (obj.equals(smartQ.getImportt())) {
	    new ImportXML();
	    guiService = new GuiService();
	    smartQ.questionariesInit(guiService.getQuizzesAndNrOfQuestions());
	    smartQ.questionInit(guiService.getQuestionsAndType());
	    JOptionPane.showMessageDialog(null, "The data has been imported from xml file!");

	}

	// /////////////////////////////////////End of
	// SmartQuest//////////////////////////////////

	if (createQuiz == true) {
	    if (obj.equals(addQuestionnaire.getCancel())) {
		addQuestionnaire.closeFrame();
		createQuiz = false;
	    }
	    if (obj.equals(addQuestionnaire.getNext())) {
		addQuestionnaire2 = new AddNewQuiz2(guiService.getQuestions());
		this.addQuestionnaire2AddListeners();
	    }
	}

	if (createQuestion == true) {

	    if (obj.equals(addQuestion.getCancel())) {
		addQuestion.closeFrame();
		createQuestion = false;
	    }
	    if (obj.equals(addQuestion.getNext())) {
		try {
		    int nrOfOptions = addQuestion.getNrOfOptions();
		    boolean good = true;

		    String type = addQuestion.getQuestionType();

		    if (good && type.equals("Multiple Choice"))
			multipleView = new MultipleChoiceWindow(nrOfOptions, "Multiple Choice");
		    else if (type.equals("Single Choice"))
			multipleView = new MultipleChoiceWindow(nrOfOptions, "Single Choice");
		    else if (type.equals("Text Answer")) {
			multipleView = new MultipleChoiceWindow(1, "Text Answer");
		    }
		    this.addQuestion2AddListeners();
		}

		catch (Exception e) {
		    JOptionPane.showMessageDialog(null, "Please enter a number!\n" + e.toString());
		}
	    }
	}

    }

    private void addQuestion2AddListeners() {
	multipleView.getBack().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		multipleView.closeFrame();
	    }
	});
	multipleView.getCancel().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		multipleView.closeFrame();
		addQuestion.closeFrame();
	    }
	});
	multipleView.getFinish().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		String type = addQuestion.getQuestionType();
		String text = addQuestion.getQuestionText();
		Question q;
		List<String> answers = new ArrayList<String>();
		answers = multipleView.getAnswers();
		if (type.equals(QuestionType.MULTIPLE_CHOICE_Q.toString())) {
		    List<Integer> correctIndexes = new ArrayList<Integer>();
		    correctIndexes = multipleView.getCorrectIndexes();
		    q = new MultipleChoiceQuestion(0, text, answers, correctIndexes);
		    try {
			QuestionDB.createQuestion(text, "MULTIPLE_CHOICE_Q");
		    } catch (Exception e1) {
			e1.printStackTrace();
		    }

		    int idQuestion = 0;
		    try {
			idQuestion = QuestionDB.getQuestionId(text);
		    } catch (Exception e1) {
			e1.printStackTrace();
		    }
		    for (int i = 0; i < answers.size(); i++) {
			if (correctIndexes.contains(i)) {
			    try {
				AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 1);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }
			} else
			    try {
				AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 0);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }
		    }
		} else if (type.equals(QuestionType.SINGLE_CHOICE_Q.toString())) {
		    int correctInd = multipleView.getCorrectIndex();
		    q = new SingleChoiceQuestion(0, text, answers, correctInd);

		    try {
			QuestionDB.createQuestion(text, "SINGLE_CHOICE_Q");
		    } catch (Exception e1) {
			e1.printStackTrace();
		    }

		    int idQuestion = 0;
		    try {
			idQuestion = QuestionDB.getQuestionId(text);
		    } catch (Exception e1) {
			e1.printStackTrace();
		    }
		    for (int i = 0; i < answers.size(); i++) {
			if (i == correctInd) {
			    try {
				AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 1);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }
			} else
			    try {
				AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 0);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }
		    }
		}

		else {
		    int idQuestion = 0;
		    q = new TextQuestion(0, text, "No answer");
		    try {
			QuestionDB.createQuestion(text, "TEXT_Q");
			idQuestion = QuestionDB.getQuestionId(text);
			AnswersDB.createAnswer(idQuestion, answers.get(0), (byte) 1);
		    } catch (Exception e1) {
			e1.printStackTrace();
		    }
		}

		try {
		    questionsService.add(q);
		} catch (MyException e1) {
		    e1.printStackTrace();
		}

		smartQ.addQuestionInTable(text, type, "Last modified unknown");
		multipleView.closeFrame();
		addQuestion.closeFrame();
	    }
	});
    }

    private void addQuestionnaireAddListeners() {
	addQuestionnaire.getCancel().addActionListener(this);
	addQuestionnaire.getNext().addActionListener(this);
    }

    private void addQuestionAddListeners() {
	addQuestion.getCancel().addActionListener(this);
	addQuestion.getNext().addActionListener(this);
    }

    private void addQuestionnaire2AddListeners() {
	addQuestionnaire2.getBack().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		addQuestionnaire2.closeFrame();
	    }
	});
	addQuestionnaire2.getCancel().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		addQuestionnaire2.closeFrame();
		addQuestionnaire.closeFrame();
	    }
	});
	addQuestionnaire2.getFinish().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		Quiz quiz = new Quiz(0, addQuestionnaire.getQuizName());
		List<Integer> questionRows = new ArrayList<Integer>();
		questionRows = addQuestionnaire2.getSelectedQuestions();
		String questions[] = new String[questionRows.size()];
		int j = 0;
		for (Integer i : questionRows) {
		    quiz.addQuestion(guiService.getQuestionsList().get(i));
		    questions[j++] = guiService.getQuestionsList().get(i).getText();
		}
		try {
		    quizzesService.add(quiz);
		} catch (MyException e1) {
		    JOptionPane.showMessageDialog(null, e1.getMessage());
		}

		try {
		    QuizDB.createQuiz(quiz.getName());
		} catch (Exception e1) {
		    e1.printStackTrace();
		}

		try {
		    RelationQuizzAndQuestionsDB.createRelation(quiz.getName(), questions);
		} catch (Exception e1) {
		    e1.printStackTrace();
		}

		smartQ.addQuizInTable(quiz.getName(), quiz.getNrOfQuestions(), "Last modified unknown");
		addQuestionnaire2.closeFrame();
		addQuestionnaire.closeFrame();
	    }
	});

	addQuestionnaire2.getSearchField().addKeyListener(this);
    }

    private void editQuizAddListeners() {
	editQuiz.getCancel().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent arg0) {
		editQuiz.closeFrame();
	    }
	});

	editQuiz.getFinish().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent arg0) {
		String name = editQuiz.getQuizName();
		List<Integer> questionsPos = editQuiz.getSelectedQuestions();
		int quizIndex = Integer.parseInt(smartQ.getEditInfo()[4]);
		List<Question> newQestionList = new ArrayList<Question>();
		for (Integer qq : questionsPos) {
		    newQestionList.add(guiService.getQuestionsList().get(qq));
		}
		Quiz quiz = ((ArrayList<Quiz>) guiService.getQuizzesList()).get(quizIndex);
		quiz.setName(name);
		quiz.setQuestionList(newQestionList);

		String data[] = new String[4];
		data[0] = name;
		data[1] = Integer.toString(newQestionList.size());
		data[2] = Calendar.getInstance().getTime().toString();
		data[3] = "Quiz";
		smartQ.updateTable(quizIndex, data, "Quiz");

		editQuiz.closeFrame();
	    }
	});

    }

    public void editQuestionAddListeners() {
	editQuestion.getCancel().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent arg0) {
		editQuestion.closeFrame();

	    }
	});


	editQuestion.getNext().addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent arg0) {

		String type = editQuestion.getQuestionType();
		int nrOfOptions = editQuestion.getNrOfOptions();

		if (type.equals("Multiple Choice"))
		    multipleView = new MultipleChoiceWindow(nrOfOptions, "Multiple Choice");
		else if (type.equals("Single Choice"))
		    multipleView = new MultipleChoiceWindow(nrOfOptions, "Single Choice");
		else if (type.equals("Text Answer"))
		    multipleView = new MultipleChoiceWindow(1, "Text Answer");
		multipleView.getCancel().addActionListener(new ActionListener() {
		    
		    @Override
		    public void actionPerformed(ActionEvent arg0) {
			multipleView.closeFrame();
		    }
		});
		multipleView.getFinish().addActionListener(new ActionListener() {

		    @Override
		    public void actionPerformed(ActionEvent e) {

			String type = editQuestion.getQuestionType();
			String oldText = smartQ.getSelectedItem();
			String newText = editQuestion.getQuestionText();

			Question q = null;
			List<String> answers = new ArrayList<String>();
			answers = multipleView.getAnswers();

			if (type.equals("Multiple Choice")) {
			    List<Integer> correctIndexes = new ArrayList<Integer>();
			    correctIndexes = multipleView.getCorrectIndexes();
			    

			    int idQuestion = 0;
			    try {
				idQuestion = QuestionDB.getQuestionId(oldText);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }
			    
			    q = new MultipleChoiceQuestion(idQuestion, newText, answers, correctIndexes);
			    try {
				QuestionDB.updateQuestion(idQuestion, newText, QuestionType.MULTIPLE_CHOICE_Q.toString());
			    } catch (SQLException e2) {
				e2.printStackTrace();
			    } catch (ClassNotFoundException e2) {
				e2.printStackTrace();
			    }
			    
			    try {
				AnswersDB.deleteAnswer(idQuestion);
			    } catch (SQLException e3) {
				e3.printStackTrace();
			    } catch (ClassNotFoundException e3) {
				e3.printStackTrace();
			    }
			    for (int i = 0; i < answers.size(); i++) {
				if (correctIndexes.contains(i)) {
				    try {
					AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 1);
				    } catch (Exception e1) {
					e1.printStackTrace();
				    }
				} else
				    try {
					AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 0);
				    } catch (Exception e1) {
					e1.printStackTrace();
				    }
			    }
			} else if (type.equals("Single Choice")) {
			    int correctInd = multipleView.getCorrectIndex();

			    int idQuestion = 0;
			    try {
				idQuestion = QuestionDB.getQuestionId(oldText);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }

			    q = new SingleChoiceQuestion(idQuestion, newText, answers, correctInd);
			    try {
				QuestionDB.updateQuestion(idQuestion, newText, QuestionType.SINGLE_CHOICE_Q.toString());
			    } catch (SQLException e2) {
				e2.printStackTrace();
			    } catch (ClassNotFoundException e2) {
				e2.printStackTrace();
			    }
			    
			    try {
				AnswersDB.deleteAnswer(idQuestion);
			    } catch (SQLException e4) {
				e4.printStackTrace();
			    } catch (ClassNotFoundException e5) {
				e5.printStackTrace();
			    }

			    for (int i = 0; i < answers.size(); i++) {
				if (i == correctInd) {
				    try {
					AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 1);
				    } catch (Exception e1) {
					e1.printStackTrace();
				    }
				} else
				    try {
					AnswersDB.createAnswer(idQuestion, answers.get(i), (byte) 0);
				    } catch (Exception e1) {
					e1.printStackTrace();
				    }
			    }
			}

			else {
			    int idQuestion = 0;
			  
			    try {
				idQuestion = QuestionDB.getQuestionId(oldText);
				q = new TextQuestion(idQuestion, newText, "No answer");
				QuestionDB.updateQuestion(idQuestion, newText, QuestionType.TEXT_Q.toString());
				
				try {
				    AnswersDB.deleteAnswer(idQuestion);
				} catch (SQLException e6) {
				    e6.printStackTrace();
				} catch (ClassNotFoundException e6) {
				    e6.printStackTrace();
				}

				AnswersDB.createAnswer(idQuestion, answers.get(0), (byte) 1);
			    } catch (Exception e1) {
				e1.printStackTrace();
			    }

			}
			try {
			    questionsService.update(q);
			} catch (MyException e1) {
			    e1.printStackTrace();
			}

			int questionIndex = Integer.parseInt(smartQ.getEditInfo()[4]);
			String data[] = new String[4];
			data[0] = q.getText();
			if(q.getType().equals(QuestionType.SINGLE_CHOICE_Q))
			data[1] = "Single Choice";
			else if (q.getType().equals(QuestionType.MULTIPLE_CHOICE_Q))
			    data[1]="Multiple Choice";
			else
			    data[1]="Text";
			data[2] = Calendar.getInstance().getTime().toString();
			data[3] = "Question";
			smartQ.updateTable(questionIndex, data, "Question");
			
			multipleView.closeFrame();
			editQuestion.closeFrame();

		    }
		});
	    }
	});

    }

    @Override
    public void keyPressed(KeyEvent arg0) {
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
	String s = addQuestionnaire2.getSearchText();
	addQuestionnaire2.searchFilterTable(s, guiService.getQuestions());
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
    }

}